#include"netclient.h"
#include"../model/datacenter.h"

network::NetClient::NetClient(model::DataCenter *dataCenter)
    :dataCenter(dataCenter)
{
    initWebSocket();
}

void network::NetClient::ping()
{
    QNetworkRequest httpReq;
    httpReq.setUrl(QUrl(HTTP_URL + "/ping"));
    QNetworkReply* httpResp = httpClient.get(httpReq);

    connect(httpResp, &QNetworkReply::finished, this, [=](){
        if(httpResp->error() != QNetworkReply::NoError){
            LOG() << "HTTP 请求失败" << httpResp->errorString();
            return;
        }

        //获取响应信息
        QByteArray respBody = httpResp->readAll();
        LOG() << "resp= " << QString(respBody);

        httpResp->deleteLater();
    });

}

QNetworkReply *network::NetClient::sendHttpRequest(const QString &apiPath, const QByteArray &body)
{
    // 1.构造http请求
    QNetworkRequest httpReq;
    httpReq.setUrl(QUrl(HTTP_URL + apiPath));
    httpReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf");

    // 2.发送http请求
    QNetworkReply* httpResp = httpClient.post(httpReq, body);
    return httpResp;
}

void network::NetClient::initWebSocket()
{
    // 1.连接信号槽
    connect(&webSocketClient, &QWebSocket::connected, this, [=](){
        LOG() << " WebSocket connect";
        //通过webSocket发送身份信息
        sendAuthentication();
    });

    connect(&webSocketClient, &QWebSocket::disconnected, this, [=](){
        LOG() << "WebSocket disconnected";
    });

    connect(&webSocketClient, &QWebSocket::errorOccurred, this, [=](){
        LOG() << "WebSocket error";
    });

    connect(&webSocketClient, &QWebSocket::textMessageReceived, this, [=](const QString& message){
        LOG() << "WebSocket textMessageReceived: " << message;
    });

    connect(&webSocketClient, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& message){
        LOG() << "WebSocket binaryMessageReceived";

        //通过⼆进制⽅式收到响应数据, 响应数据是 pb 的 NotifyMessage 结构
        std::shared_ptr<lx::NotifyMessage> respObj = std::make_shared<lx::NotifyMessage>();
        respObj->deserialize(&serializer, message);
        handleWsResponse(respObj);
    });

    // 2. 建⽴ websocket 连接
    webSocketClient.open(WEBSOCKET_URL);
}

QString network::NetClient::makeRequestId()
{
    return "R" + QUuid::createUuid().toString().sliced(25, 12);
}

void network::NetClient::sendAuthentication()
{
    // 1.判断WebSocket是否连接有效
    if(!webSocketClient.isValid()){
        LOG() << "WebSokect 连接无效";
        return;
    }

    // 2. 初始化认证请求并发送
    lx::ClientAuthenticationReq req;
    req.setRequestId(makeRequestId());
    req.setRequestId("");
    req.setSessionId(dataCenter->getLoginSessionId());
    QByteArray body = req.serialize(&serializer);
    webSocketClient.sendBinaryMessage(body);

    LOG() << "[ws身份认证] requestId= " << req.requestId() << ", longinSessionId= " << req.sessionId();
}

void network::NetClient::handleWsResponse(std::shared_ptr<lx::NotifyMessage> &notifyMessage)
{
    if(notifyMessage->notifyType() == lx::NotifyTypeGadget::CHAT_MESSAGE_NOTIFY){
        //把pb中的messageInfo转换成客户端自己的message
        model::Message message;
        message.load(notifyMessage->newMessageInfo().messageInfo());
        handleWsMessage(message);
    }
    else if(notifyMessage->notifyType() == lx::NotifyTypeGadget::FRIEND_REMOVE_NOTIFY){
        //删除好友通知
        const QString& userId = notifyMessage->friendRemove().userId();
        handleWsRemoveFriend(userId);
    }
    else if(notifyMessage->notifyType() == lx::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY){
        // 添加好友申请通知
        model::UserInfo userInfo;
        userInfo.load(notifyMessage->friendAddApply().userInfo());
        handleWsAddFriendApply(userInfo);
    }
    else if (notifyMessage->notifyType() == lx::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY) {
        // 添加好友申请的处理结果通知
        model::UserInfo userInfo;
        userInfo.load(notifyMessage->friendProcessResult().userInfo());
        bool agree = notifyMessage->friendProcessResult().agree();
        handleWsAddAndRejectFriendProcess(userInfo, agree);
    }
    else if(notifyMessage->notifyType() == lx::NotifyTypeGadget::CHAT_SESSION_CREATE_NOTIFY){
        //创建新的会话
        model::ChatSessionInfo chatSessionInfo;
        chatSessionInfo.load(notifyMessage->newChatSessionInfo().chatSessionInfo());
        handleWsSessionCreate(chatSessionInfo);
    }
    else{
        return;
    }
}

void network::NetClient::handleWsMessage(const model::Message &message)
{
    auto messageList = dataCenter->getRecentMessages(message.chatSessionId);
    if(messageList == nullptr){
        //还没从网络获取到消息列表，就先从网络加载
        connect(dataCenter, &model::DataCenter::getRecentMessagesDoneNoUI, dataCenter, &model::DataCenter::receiveMessage, Qt::UniqueConnection);

        dataCenter->getRencentMessagesAsync(message.chatSessionId, false);
    }
    else{
        //本地已经有消息列表了，直接添加进去
        messageList->push_back(message);
        dataCenter->receiveMessage(message.chatSessionId);
    }
}

void network::NetClient::closeWebSocket()
{
    webSocketClient.close();
    LOG() << "close WebSocketClient";
}

void network::NetClient::getMyselfInfo(const QString &loginSessionId)
{
    lx::GetUserInfoReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[获取个⼈信息] requestId=" << req.requestId() << ", sessionId=" << loginSessionId;

    // 2. 发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/user/get_user_info", body);

    // 3. 处理http请求
    connect(resp, &QNetworkReply::finished, this, [=](){
        // 1.解析响应
        auto userInfoResp = this->handleHttpResponse<lx::GetUserInfoRsp>(resp);

        if(!userInfoResp){
            return;
        }

        // 2.设置dataCenter中的数据
        dataCenter->setMySelfInfo(userInfoResp);

        //发送信号
        emit dataCenter->getMyselfInfoDone();
    });
}

void network::NetClient::getFriendList(const QString &loginSessionId)
{
    lx::GetFriendListReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);

    QByteArray body = req.serialize(&serializer);

    QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_friend_list", body);

    connect(resp, &QNetworkReply::finished, this, [=](){
        auto FriendListResp = this->handleHttpResponse<lx::GetFriendListRsp>(resp);

        if(!FriendListResp){
            return;
        }

        //设置dataCenter中的数据
        dataCenter->setFriendList(FriendListResp);

        //发送信号
        emit dataCenter->getFriendListDone();
    });
}

void network::NetClient::getSessionList(const QString &loginSessionId)
{
    lx::GetChatSessionListReq Req;
    Req.setRequestId(makeRequestId());
    Req.setSessionId(loginSessionId);
    LOG() << "[获取会话列表] requestId=" << Req.requestId() << ", loginSessionId=" << loginSessionId;

    //序列化
    QByteArray body = Req.serialize(&serializer);

    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/get_chat_session_list", body);

    connect(httpResp, &QNetworkReply::finished, this, [=]{
        auto sessionListResp = this->handleHttpResponse<lx::GetChatSessionListRsp>(httpResp);

        if(!sessionListResp){
            return;
        }

        //设置dataCenter中的数据
        dataCenter->setSessionList(sessionListResp);

        //发送信号
        emit dataCenter->getSessionListDone();
    });
}

void network::NetClient::getApplyList(const QString &loginSessionId)
{
    //构造body
    lx::GetPendingFriendEventListReq Req;
    Req.setRequestId(makeRequestId());
    Req.setSessionId(loginSessionId);
    LOG() << "[获取好友申请列表] requestId=" << Req.requestId() << ", loginSessionId=" << loginSessionId;

    //序列化
    QByteArray body = Req.serialize(&serializer);

    //发送http请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/get_pending_friend_events", body);

    connect(httpResp, &QNetworkReply::finished, this, [=](){
        auto applyListResp = this->handleHttpResponse<lx::GetPendingFriendEventListRsp>(httpResp);

        if(!applyListResp){
            return;
        }

        //设置dataCenter中的数据
        dataCenter->setApplyList(applyListResp);

        //发送信号
        emit dataCenter->getApplyListDone();
    });
}

void network::NetClient::getRecentMessages(const QString &loginSessionId, const QString &chatSessionId, bool isUpdateUI)
{
    //构造body
    lx::GetRecentMsgReq Req;
    Req.setSessionId(loginSessionId);
    Req.setChatSessionId(chatSessionId);
    Req.setMsgCount(50); //获取50条消息，不够按实际数目展示
    Req.setRequestId(makeRequestId());

    QByteArray body = Req.serialize(&serializer);

    LOG() << "[获取最近消息] requestId=" << Req.requestId() << ", sessionId=" << loginSessionId << ", chatSessionId=" << chatSessionId;

    QNetworkReply* httpResp = this->sendHttpRequest("/service/message_storage/get_recent", body);
    connect(httpResp, &QNetworkReply::finished, this, [=](){
        auto recentResp = this->handleHttpResponse<lx::GetRecentMsgRsp>(httpResp);

        if(!recentResp){
            LOG() << "获取历史消息列表失败";
            return;
        }
        if(!recentResp->success()){
            LOG() << "获取历史消息列表失败! " << recentResp->errmsg();
            return;
        }

        dataCenter->setRecentMessages(chatSessionId, recentResp);

        if(isUpdateUI){
            emit dataCenter->getRecentMessagesDone(chatSessionId);
        }
        else{
            emit dataCenter->getRecentMessagesDoneNoUI(chatSessionId);
        }
    });
}

void network::NetClient::sendMessage(const QString &loginSessionId, const QString &chatSessionId,
                                         model::MessageType messageType, const QByteArray &content, const QString& extraInfo)
{
    lx::NewMessageReq Req;
    Req.setRequestId(makeRequestId());
    Req.setChatSessionId(chatSessionId);
    Req.setSessionId(loginSessionId);

    lx::MessageContent messageContent;

    if(messageType == model::MessageType::TEXT_TYPE){
        lx::StringMessageInfo stringMessageInfo;
        stringMessageInfo.setContent(content);
        messageContent.setMessageType(lx::MessageTypeGadget::MessageType::STRING);
        messageContent.setStringMessage(stringMessageInfo);
    }
    else if(messageType == model::MessageType::FILE_TYPE){
        lx::FileMessageInfo fileMessageInfo;
        fileMessageInfo.setFileId("");
        fileMessageInfo.setFileName(extraInfo);
        fileMessageInfo.setFileContents(content);
        fileMessageInfo.setFileSize(content.size());
        messageContent.setMessageType(lx::MessageTypeGadget::MessageType::FILE);
        messageContent.setFileMessage(fileMessageInfo);
    }
    else if(messageType == model::MessageType::IMAGE_TYPE){
        lx::ImageMessageInfo imageMessageInfo;
        imageMessageInfo.setFileId("");
        imageMessageInfo.setImageContent(content);
        messageContent.setMessageType(lx::MessageTypeGadget::MessageType::IMAGE);
        messageContent.setImageMessage(imageMessageInfo);
    }
    else if(messageType == model::MessageType::SPEECH_TYPE){
        lx::SpeechMessageInfo speechMessageInfo;
        speechMessageInfo.setFileId("");
        speechMessageInfo.setFileContents(content);
        messageContent.setMessageType(lx::MessageTypeGadget::MessageType::SPEECH);
        messageContent.setSpeechMessage(speechMessageInfo);
    }
    else{
        qCritical() << TAG << "未知的 MessageType! messageType=" << messageType;
        return;
    }
    Req.setMessage(messageContent);

    QByteArray body = Req.serialize(&serializer);
    LOG() << "[发送消息] requestId=" << Req.requestId() << ", sessionId=" << loginSessionId << ", chatSessionId=" << chatSessionId;

    QNetworkReply* httpResp = this->sendHttpRequest("/service/message_transmit/new_message", body);

    connect(httpResp, &QNetworkReply::finished, this, [=](){
        auto resp = this->handleHttpResponse<lx::NewMessageRsp>(httpResp);

        if (!resp) {
            LOG() << "发送消息失败";
            return;
        }
        if (!resp->success()) {
            LOG() << "发送消息失败! " << resp->errmsg();
            emit dataCenter->sendMessageFailed(resp->errmsg());
            return;
        }

        //发送信号
        emit dataCenter->sendMessageDone(messageType, content, extraInfo);
    });
}

void network::NetClient::changeNickName(const QString &loginSessionId, const QString &name)
{
    lx::SetUserNicknameReq Req;
    Req.setNickname(name);
    Req.setRequestId(makeRequestId());
    Req.setSessionId(loginSessionId);
    QByteArray body = Req.serialize(&serializer);
    LOG() << "[修改⽤⼾昵称] requestId=" << Req.requestId() << ", sessionId=" << loginSessionId << ", nickName=" << name;

    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/set_nickname", body);
    connect(httpResp, &QNetworkReply::finished, this, [=](){
        auto resp = this->handleHttpResponse<lx::SetUserNicknameRsp>(httpResp);

        if(resp == nullptr){
            return;
        }

        // b) 修改数据
        dataCenter->setName(name);
        // c) 发送信号
        emit dataCenter->changeNickNameDone();
    });
}

void network::NetClient::changeDescription(const QString &loginSessionId, const QString &description)
{
    // 1. 构造请求
    lx::SetUserDescriptionReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setDescription(description);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[修改⽤⼾昵称] requestId=" << req.requestId() << ", sessionId=" << loginSessionId << ", description=" << description;

    // 2. 发送 http 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/set_description", body);

    // 3. 处理 http 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // 解析响应
        auto resp = this->handleHttpResponse<lx::SetUserDescriptionRsp>
        (httpResp);

        if (!resp) {
            // shared_ptr 可以直接通过 bool 运算判定是否是空对象.
            return;
        }
        // 修改数据
        dataCenter->setDescription(description);
        // 发送信号
        emit dataCenter->changeDescriptionDone();
    });
}

void network::NetClient::getVerifyCode(const QString &phone)
{
    // 1. 构造请求
    lx::PhoneVerifyCodeReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phone);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[获取验证码] requestId=" << req.requestId() << " phoneNumber=" << phone;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/get_phone_verify_code", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::PhoneVerifyCodeRsp>(httpResp);

        if (!resp) {
            return;
        }
        // b) 修改数据
        dataCenter->setVerifyCodeId(resp->verifyCodeId());
        // c) 发送信号
        emit dataCenter->getVerifyCodeDone();
    });
}

void network::NetClient::changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    // 1. 构造请求
    lx::SetUserPhoneNumberReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setPhoneNumber(phone);
    req.setPhoneVerifyCodeId(verifyCodeId);
    req.setPhoneVerifyCode(verifyCode);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[修改⼿机号] requestId=" << req.requestId() << " phoneNumber=" <<
        phone << " verifyCodeId=" << verifyCodeId << " verifyCode=" << verifyCode;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/set_phone", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::SetUserPhoneNumberRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 修改数据
        dataCenter->setPhone(phone);
        // c) 发送信号
        emit dataCenter->changePhoneDone();
    });
}

void network::NetClient::changeAvatar(const QString& loginSessionId, const QByteArray &avatar)
{
    // 1. 构造请求
    lx::SetUserAvatarReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setAvatar(avatar);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[修改头像] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/set_avatar", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::SetUserAvatarRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 修改数据
        dataCenter->setAvatar(avatar);
        // c) 发送信号
        emit dataCenter->changeAvatarDone();
    });
}

void network::NetClient::deleteFriend(const QString &loginSessionId, const QString &userId)
{
    // 1. 构造请求
    lx::FriendRemoveReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setPeerId(userId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[删除好友] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " userId=" << userId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/remove_friend", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::FriendRemoveRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 修改数据
        dataCenter->removeFriend(userId);
        // c) 发送信号
        emit dataCenter->deleteFriendDone(userId);
    });
}

void network::NetClient::handleWsRemoveFriend(const QString &userId)
{
    // 服务器告知客⼾端, 某个好友把你删了.
    // 1. 从 DataCenter 中删除好友
    dataCenter->removeFriend(userId);
    // 2. 通知界⾯变化
    emit dataCenter->deleteFriendDone(userId);
}

void network::NetClient::handleWsAddFriendApply(const model::UserInfo &userInfo)
{
    //添加到applyList中
    auto applyList = dataCenter->getApplyList();
    if(!applyList){
        LOG() << "applyList 本地不存在";
        return;
    }

    //如果该好友申请已经存在就不做处理
    for(const auto& a : *applyList){
        if(a.userId == userInfo.userId){
            LOG() << "好友申请已经存在";
            return;
        }
    }

    //不存在添加到列表中
    applyList->push_front(userInfo);

    //通知界面新增一个内容
    emit dataCenter->receiveFriendApplyDone();
}

void network::NetClient::handleWsAddAndRejectFriendProcess(const model::UserInfo &userInfo, bool agree)
{
    // 告诉客⼾端是否对⽅是否同意好友申请
    if (agree) {
        // 1. 添加数据到好友列表中
        QList<model::UserInfo>* friendList = dataCenter->getFriendList();
        if (friendList == nullptr) {
            qCritical() << TAG << "本地不存在 friendList";
            return;
        }
        friendList->push_front(userInfo);

        // 2. 告知界⾯同意好友申请
        emit dataCenter->receiveFriendProcessAccept(userInfo);
    }
    else {
        emit dataCenter->receiveFriendProcessReject(userInfo);
    }
}

void network::NetClient::handleWsSessionCreate(const model::ChatSessionInfo &chatSessionInfo)
{
    QList<model::ChatSessionInfo>* chatSessionList = dataCenter->getSessionList();
    if (chatSessionList == nullptr) {
        qCritical() << TAG << "本地不存在 chatSessionList";
        return;
    }
    // 添加到列表头部
    chatSessionList->push_front(chatSessionInfo);
    // 通知界⾯新增⼀个内容
    emit dataCenter->receiveSessionCreateDone();
}

void network::NetClient::addFriendApply(const QString &loginSessionId, const QString &userId)
{
    // 1. 构造请求
    lx::FriendAddReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setRespondentId(userId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[添加好友] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " userId=" << userId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/add_friend_apply", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::FriendAddRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 发送信号
        emit dataCenter->addFriendApplyDone();
    });
}

void network::NetClient::acceptFriendApply(const QString &loginSessionId, const QString &userId)
{
    // 1. 构造请求
    lx::FriendAddProcessReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setNotifyEventId("");
    req.setAgree(true);
    req.setApplyUserId(userId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[同意好友申请] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " userId=" << userId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/add_friend_process", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::FriendAddProcessRsp>(httpResp);
        if (!resp) {
            return;
        }
        if (resp->success()) {
            // b) 如果成功, 就把这个⽤⼾从申请列表中删除, 添加到好友列表中.
            model::UserInfo applyUser = dataCenter->removeFromApplyList(userId);
            QList<model::UserInfo>* friendList = dataCenter->getFriendList();
            friendList->push_front(applyUser);
        } else {
            // c) 如果失败, 则单纯从⽤⼾申请列表删除即可.
            dataCenter->removeFromApplyList(userId);
        }
        // d) 发送信号, 更新界⾯
        emit dataCenter->acceptFriendApplyDone(userId, resp->errmsg());
    });
}

void network::NetClient::rejectFriendApply(const QString &loginSessionId, const QString &userId)
{
    // 1. 构造请求
    lx::FriendAddProcessReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setNotifyEventId("");
    req.setAgree(false);
    req.setApplyUserId(userId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[拒绝好友申请] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " userId=" << userId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/add_friend_process", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::FriendAddProcessRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 把该⽤⼾从 applyList 中删除
        dataCenter->removeFromApplyList(userId);
        // c) 发送信号
        emit dataCenter->rejectFriendApplyDone(userId, resp->errmsg());
    });
}

void network::NetClient::createChatSession(const QString& loginSessionId, const QList<QString> &userIdList)
{
    // 1. 构造请求
    lx::ChatSessionCreateReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionName("新的群聊");
    req.memberIdList() = userIdList;
    QByteArray body = req.serialize(&serializer);
    LOG() << "[创建群聊会话] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/create_chat_session", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::ChatSessionCreateRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 修改会话列表操作不需要在这⾥进⾏. 虽然在 HTTP 响应这⾥会返回⼀个会话对象详情.
            // 但是我们忽略这个响应
            // 并且服务器会在创建会话完成后, 通过 ws 给会话中所有成员推送会话创建信息.
            // c) 发送信号
            emit dataCenter->createChatSessionDone();
    });
}

void network::NetClient::getMemberList(const QString& loginSessionId, const QString &chatSessionId)
{
    // 1. 构造请求
    lx::GetChatSessionMemberReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[获取群聊成员列表] requestId=" << req.requestId() << "loginSessionId=" << loginSessionId << " chatSessionId=" << chatSessionId;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/get_chat_session_member", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::GetChatSessionMemberRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 修改会话列表操作不需要在这⾥进⾏. 虽然在 HTTP 响应这⾥会返回⼀个会话对象详情.
            // 但是我们忽略这个响应
            // 并且服务器会在创建会话完成后, 通过 ws 给会话中所有成员推送会话创建信息.
            dataCenter->setMemberList(chatSessionId, resp);
        // c) 发送信号
        emit dataCenter->getMemberListDone(chatSessionId);
    });
}

void network::NetClient::searchUser(const QString &loginSessionId, const QString &searchKey)
{
    // 1. 构造请求
    lx::FriendSearchReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setSearchKey(searchKey);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[搜索⽤⼾] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " searchKey=" << searchKey;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/search_friend", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
    // a) 解析响应
        auto resp = this->handleHttpResponse<lx::FriendSearchRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 获取到的结果数据
        dataCenter->setSearchUserResult(resp);
        // c) 发送信号
        emit dataCenter->searchUserDone();
    });
}

void network::NetClient::searchMessage(const QString &loginSessionId, const QString& chatSessionId, const QString &searchKey)
{
    // 1. 构造请求
    lx::MsgSearchReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    req.setSearchKey(searchKey);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[按词搜索消息] requestId=" << req.requestId() << " loginSessionId=" << loginSessionId << " searchKey=" << searchKey;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/message_storage/search_history", body);

        // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::MsgSearchRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 获取到的结果数据
        dataCenter->setSearchMessageResult(resp->msgList());
        // c) 发送信号
        emit dataCenter->searchMessageDone();
    });
}

void network::NetClient::searchMessageByTime(const QString &loginSessionId, const QString &chatSessionId, const QDateTime begTime, const QDateTime endTime)
{
    // 1. 构造请求
    lx::GetHistoryMsgReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    req.setStartTime(begTime.toSecsSinceEpoch());
    req.setOverTime(endTime.toSecsSinceEpoch());

    QByteArray body = req.serialize(&serializer);
    LOG() << "[按时间搜索消息] requestId=" << req.requestId() << "loginSessionId=" << loginSessionId
          << " begTime=" << begTime << " endTime=" << endTime;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/message_storage/get_history", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::GetHistoryMsgRsp>(httpResp);
        if (!resp) {
            return;
        }
        // b) 获取到的结果数据
        dataCenter->setSearchMessageResult(resp->msgList());
        // c) 发送信号
        emit dataCenter->searchMessageDone();
    });
}

void network::NetClient::userLogin(const QString &username, const QString &password)
{
    // 1. 构造请求
    lx::UserLoginReq req;
    req.setRequestId(makeRequestId());
    req.setNickname(username);
    req.setPassword(password);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[⽤⼾名登录] requestId=" << req.requestId() << " username=" << username << " password=" << password;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/username_login", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::UserLoginRsp>(httpResp);
        if (!resp) {
            // 失败也发送⼀个信号, 告知原因
            emit dataCenter->userLoginDone(false, "⽹络故障");
            return;
        }
        if (!resp->success()) {
            emit dataCenter->userLoginDone(false, resp->errmsg());
            return;
        }
        // b) 获取到的结果数据
        dataCenter->setLoginSessionId(resp->loginSessionId());
        // c) 发送信号
        emit dataCenter->userLoginDone(true, "");
    });
}

void network::NetClient::userRegister(const QString &username, const QString &password)
{
    // 1. 构造请求
    lx::UserRegisterReq req;
    req.setRequestId(makeRequestId());
    req.setNickname(username);
    req.setPassword(password);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[⽤⼾名注册] requestId=" << req.requestId() << " username=" << username << " password=" << password;

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/username_register", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::UserRegisterRsp>(httpResp);
        if (!resp) {
            emit dataCenter->userRegisterDone(false, "⽹络故障");
            return;
        }
        if (!resp->success()) {
            emit dataCenter->userRegisterDone(false, resp->errmsg());
            return;
        }
        // b) 获取到的结果数据.
        // 对于注册来说, 不需要任何数据
        // c) 发送信号
        emit dataCenter->userRegisterDone(true, "");
    });
}

void network::NetClient::phoneLogin(const QString &phone, const QString &phoneVerifyCode)
{
    // 1. 构造请求
    lx::PhoneLoginReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phone);
    req.setVerifyCodeId(dataCenter->getVerifyCodeId());
    req.setVerifyCode(phoneVerifyCode);
    QByteArray body = req.serialize(&serializer);

    LOG() << "[⼿机号登录] requestId=" << req.requestId() << " phone=" << phone<< " verifyCodeId=" << req.verifyCodeId()
          << " verifyCode=" << req.verifyCode();

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/phone_login", body);

    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // a) 解析响应
        auto resp = this->handleHttpResponse<lx::PhoneLoginRsp>(httpResp);
        if (!resp) {
            emit dataCenter->phoneLoginDone(false, "⽹络故障");
            return;
        }
        if (!resp->success()) {
            emit dataCenter->phoneLoginDone(false, resp->errmsg());
            return;
        }
        // b) 获取到的结果数据
        dataCenter->setLoginSessionId(resp->loginSessionId());
        // c) 发送信号
        emit dataCenter->phoneLoginDone(true, "");
    });
}

void network::NetClient::phoneRegister(const QString &phone, const QString &phoneVerifyCode)
{
    // 1. 构造请求
    lx::PhoneRegisterReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phone);
    req.setVerifyCodeId(dataCenter->getVerifyCodeId());
    req.setVerifyCode(phoneVerifyCode);

    QByteArray body = req.serialize(&serializer);
    LOG() << "[⼿机号登录] requestId=" << req.requestId() << " phone=" << phone
          << " verifyCodeId=" << req.verifyCodeId() << " verifyCode=" << req.verifyCode();

    // 2. 发送 HTTP 请求
    QNetworkReply* httpResp = this->sendHttpRequest("/service/user/phone_register", body);
    // 3. 处理 HTTP 响应
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
    // a) 解析响应
        auto resp = this->handleHttpResponse<lx::PhoneRegisterRsp>(httpResp);
        if (!resp) {
            emit dataCenter->phoneRegisterDone(false, "⽹络故障");
            return;
        }
        if (!resp->success()) {
            emit dataCenter->phoneRegisterDone(false, resp->errmsg());
            return;
        }
        // b) 获取到的结果数据
        // 注册操作不需要获取到结果
        // c) 发送信号
        emit dataCenter->phoneRegisterDone(true, "");
    });
}

template<class T>
std::shared_ptr<T> network::NetClient::handleHttpResponse(QNetworkReply *httpResp)
{
    // 1.判断请求是否成功
    if(httpResp->error() != QNetworkReply::NoError){
        LOG() << "HTTP 请求失败" << httpResp->errorString();
        return std::shared_ptr<T>();
    }

    // 2.获取响应信息body
    QByteArray body = httpResp->readAll();

    // 3.反序列化
    std::shared_ptr<T> respObj = std::make_shared<T>();
    respObj->deserialize(&serializer, body);

    // 4.判断响应结果是否正确
    if(!respObj->success()){
        LOG() << "request_id= " << respObj->requestId() << ", errmsg= " << respObj->errmsg();
        httpResp->deleteLater();

        return std::shared_ptr<T>();
    }

    // 5.打印日志
    LOG() << "request_id= " << respObj->requestId() << "响应完成";

    // 6.释放响应对象
    httpResp->deleteLater();
    return respObj;


}

// template<class T>
// std::shared_ptr<T> network::NetClient::handleHttpResponseWithReason(QNetworkReply *httpResp)
// {
//     if (httpResp->error() != QNetworkReply::NoError) {
//         LOG()<< "HTTP 请求失败: " << httpResp->errorString();
//         httpResp->deleteLater();
//         return std::shared_ptr<T>();
//     }

//     // a) 获取到响应 body
//     QByteArray respBody = httpResp->readAll();

//     // b) 反序列化
//     std::shared_ptr<T> respObj = std::make_shared<T>();
//     respObj->deserialize(&serializer, respBody);

//     // c) 判定响应结果是否正确
//     if (!respObj->success()) {
//         LOG() << "request_id=" << respObj->requestId() << ", errmsg=" << respObj->errmsg();
//         httpResp->deleteLater();
//         return respObj;
//     }

//     // c) 打印⽇志
//     LOG() << "request_id=" << respObj->requestId() << " 响应完成";
//     // d) 释放响应对象
//     httpResp->deleteLater();
//     return respObj;
// }
